﻿using Autofac;
using Common;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DBContext;
using EV.EventBus;
using HandyControl.Tools.Extension;
using NPOI.SS.Formula.Functions;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using ZoneLine.Common;
using ZoneLine.Models;
using ZoneLine.Models.PackageModel;
using ZoneLine.Models.PrintRecord;
using ZoneLine.Models.StationConfig;
using ZoneLine.Printers;
using ZoneLine.Views;

namespace ZoneLine.ViewModels
{
    public class LableCompenstateViewModel : ObservableObject
    {
        private IModelDAL _dal;
        public LableCompenstateViewModel(IModelDAL dal)
        {
            _dal = dal;
            PackageScanConfig = _dal.GetModel<PackageScanBarConfig>(p => true);
        }

        private string productNo;

        public string ProductNo
        {
            get { return productNo; }
            set => SetProperty(ref productNo, value);
        }

        private int productCount;

        public int ProductCount
        {
            get { return productCount; }
            set => SetProperty(ref productCount, value);
        }

        private string labelCode;

        public string LabelCode
        {
            get { return labelCode; }
            set => SetProperty(ref labelCode, value);
        }

        private List<AbsPrintResult> absPrintResultList;

        public List<AbsPrintResult> AbsPrintResultList
        {
            get { return absPrintResultList; }
            set => SetProperty(ref absPrintResultList, value);
        }

        private List<LableCompenState> lableCompenStateList;

        public List<LableCompenState> LableCompenStateList
        {
            get { return lableCompenStateList; }
            set => SetProperty(ref lableCompenStateList, value);
        }


        private RelayCommand queryLableInfo;

        public RelayCommand QueryLableInfo
        {
            get { return queryLableInfo ?? (queryLableInfo = new RelayCommand(SearchLableInfo)); }
        }

        public RelayCommand printLabelCode;

        public RelayCommand PrintLabelCode
        {
            get { return printLabelCode ?? (printLabelCode = new RelayCommand(PrintLabelCodeInfo)); }
        }

        public RelayCommand queryLableByAbsCode;

        public RelayCommand QueryLableByAbsCode
        {
            get { return queryLableByAbsCode ?? (queryLableByAbsCode = new RelayCommand(QueryLableByAbsCodeList)); }
        }

        private bool isOpenCheck = ApiHelper.IsOpenCheck;

        public bool IsOpenCheck
        {
            get { return isOpenCheck; }
            set
            {
                AuthView authView = new AuthView(() =>
                {
                    isOpenCheck = value;
                    ApiHelper.IsOpenCheck = isOpenCheck;
                    Logger.Log.Info($"来料检测启用情况：{ApiHelper.IsOpenCheck}");
                    SetProperty(ref isOpenCheck, value);
                });
                authView.ShowDialog();
            }
        }


        private void QueryLableByAbsCodeList()
        {
            LableCompenStateList = _dal.GetModelList<LableCompenState>(l => l.AbsCode.Contains(ProductNo));
            ProductCount = LableCompenStateList.Count;
        }

        /// <summary>
        /// 查询列表
        /// </summary>
        private void SearchLableInfo()
        {
            AbsPrintResultList = _dal.GetModelList<AbsPrintResult>(a => a.AbsCode == productNo);
            if (!AbsPrintResultList.Any())
            {
                MessageBox.Show("未查询到当前产品的标签信息！");
                return;
            }
            LabelCode = AbsPrintResultList.First().Code;
        }

        private AbsPrintResult absPrintResultInfo;

        private void PrintLabelCodeInfo()

        {
            if (labelCode == null)
            {
                return;
            }
            absPrintResultInfo = absPrintResultList.Find(f => f.Code.Equals(labelCode));
            Task.Run(() =>
            {
                PrintLabel(absPrintResultInfo);
            });
        }

        private void PrintLabel(AbsPrintResult absPrintResultInfo)
        {
            int leftOrRight = absPrintResultInfo.LeftRight;
            string productType = absPrintResultInfo.Brand;
            IPrinter printer = null;
            var config = ContainerServer.Container.Resolve<PrintConfigTotal>();
            var templatePath = string.Empty;
            (Dictionary<string, string>, string) ps = (null, null);
            switch (productType)
            {
                case "LX":
                    printer = new LXQCPrinter();
                    if (leftOrRight == (int)WorkDirectionEnum.Left)
                    {
                        templatePath = config.LxqcConfig.TemplatePath;
                    }
                    else
                    {
                        templatePath = config.LxqcConfig.TemplatePathR;
                    }
                    ps = GetLXQPara();
                    break;

                case "SQ":
                    printer = new SQQCPrinter();
                    if (leftOrRight == (int)WorkDirectionEnum.Left)
                    {
                        templatePath = config.Sqqc_Config.TemplatePath;
                    }
                    else
                    {
                        templatePath = config.Sqqc_Config.TemplatePathR;
                    }
                    ps = GetSQPara();
                    break;

                case "BQKH":
                    printer = new BQKHPrinter();
                    if (leftOrRight == (int)WorkDirectionEnum.Left)
                    {
                        templatePath = config.BqqcKhConfig.TemplatePath;
                    }
                    else
                    {
                        templatePath = config.BqqcKhConfig.TemplatePathR;
                    }
                    ps = GetBQKHPara();
                    break;

                case "BQLH":
                    printer = new BQLHPrinter();
                    if (leftOrRight == (int)WorkDirectionEnum.Left)
                    {
                        templatePath = config.BqqcLHConfig.TemplatePath;
                    }
                    else
                    {
                        templatePath = config.BqqcLHConfig.TemplatePathR;
                    }
                    ps = GetBQLHPara();
                    break;

                case "WL":
                    printer = new WLQCPrinter();
                    if (leftOrRight == (int)WorkDirectionEnum.Left)
                    {
                        templatePath = config.WlqcConfig.TemplatePath;
                    }
                    else
                    {
                        templatePath = config.WlqcConfig.TemplatePathR;
                    }
                    ps = GetWLPara();
                    break;

                default:
                    break;
            }
            if (printer != null)
            {
                try
                {
                    if (ps == (null, null)) return;
                    var stationConfig = StationEnableConfig.GetPara();
                    string printName = "";
                    if (stationConfig.OP050RStationEnable == 1)
                    {
                        var station050RConfig = _dal.GetModel<QOP050RStationConfig>(p => true);
                        printName = station050RConfig.PrinterName;
                    }
                    else
                    {
                        var statiion40Config = _dal.GetModel<HOP040StationConfig>(p => true);
                        printName = statiion40Config.PrinterName;
                    }
                    PrinterHelper.PrinterLabel(templatePath, printName, ps.Item1);
                    //打印成功，将数据打印的数据记录到关联表中
                    LableCompenState lableCompenState = new LableCompenState();
                    lableCompenState.AbsCode = absPrintResultInfo.AbsCode;
                    lableCompenState.Code = LabelCode;
                    lableCompenState.Brand = absPrintResultInfo.Brand;
                    lableCompenState.LeftRight = absPrintResultInfo.LeftRight;
                    lableCompenState.PrintTime = DateTime.Now;
                    _dal.AddModel<LableCompenState>(lableCompenState);
                }
                catch (Exception ex)
                {
                }
            }
        }

        #region LXQ

        private (Dictionary<string, string>, string) GetLXQPara()
        {
            var lxConfig = _dal.GetModel<LXRecord>(g => g.Code.Equals(LabelCode));
            if (lxConfig == null) return (null, null);
            var paras = new Dictionary<string, string>();
            var para = StationEnableConfig.GetPara();

            //供应商代码，固定
            paras.Add("GYSDM_N1", lxConfig.SupplyNo);
            //零部件序列号 固定
            var serialNo = GetPartSerialNo(lxConfig.SerialNumber);
            //paras.Add("LBJXLH_N1", serialNo);

            //生产批次
            var batchNo = GetProductBatch();
            paras.Add("LBJXLH_B_N1", batchNo + "/" + serialNo);
            paras.Add("BBH_N1", lxConfig.Version);
            var partNo = string.Empty;
            if (absPrintResultInfo.LeftRight == (int)WorkDirectionEnum.Left)
            {
                partNo = lxConfig.PartNoL;
            }
            else
            {
                partNo = lxConfig.PartNoR;
            }
            var code = $"{partNo}/{lxConfig.SupplyNo}/{batchNo}/{serialNo}/{lxConfig.Version}";
            paras.Add("LBJBH_N1", partNo);
            paras.Add("EWM_N1", code);
            if (absPrintResultInfo.LeftRight == (int)WorkDirectionEnum.Left)
            {
                if (Cache.IsHopStaion)
                    paras.Add("JQFX_N1", "RL");
                else if (Cache.IsQopStaion)
                    paras.Add("JQFX_N1", "FL");
            }
            else
            {
                if (Cache.IsHopStaion)
                    paras.Add("JQFX_N1", "RR");
                else if (Cache.IsQopStaion)
                    paras.Add("JQFX_N1", "FR");
            }
            return (paras, code);
        }

        /// <summary>
        /// 生产批次
        /// </summary>
        /// <returns></returns>
        private string GetProductBatch()
        {
            string[] args = labelCode.Split('/');
            string fourthPart = args[3];
            var year = fourthPart.Substring(0, 2);
            var mouth = fourthPart.Substring(2, 1);
            var day = fourthPart.Substring(3, 2);
            return $"{year}{mouth}{day}";
        }

        /// <summary>
        /// 生产批次
        /// </summary>
        /// <returns></returns>
        private string GetPartSerialNo(int index)
        {
            var temp = GetProductBatch();
            var rlt = index.ToString("50000");
            return $"{temp}{rlt}";
        }

        #endregion LXQ

        #region SQ

        private (Dictionary<string, string>, string) GetSQPara()
        {
            var configD = _dal.GetModel<SQRecord>(g => g.Code.Equals(LabelCode));
            var paras = new Dictionary<string, string>();
            paras.Add("FXH_N2", configD.ValveNumber);
            // 可追溯条码 生成
            var serial = GetSerial(configD.SerialNumber);
            paras.Add("KZSHM_N2", serial);
            paras.Add("SCRQ_N2", DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString("00") + DateTime.Now.Day.ToString("00"));
            paras.Add("GYSJC_N2", configD.SupplierAbbreviation);
            //var para = StationEnableConfig.GetPara();
            string code = "";
            if (Cache.WorkDirection == WorkDirectionEnum.Left)
            {
                paras.Add("JQFX_N2", "L");
                paras.Add("LBJHM_N2", configD.PartNoL);
                var partNumTemp = configD.PartNoL.Substring(configD.PartNoL.Length - 4);
                code = $"{configD.PartIdentificationCode}{partNumTemp}{configD.SupplierCode}{serial}";
                paras.Add("EWM_N2", code);
            }
            else
            {
                paras.Add("JQFX_N2", "R");
                paras.Add("LBJHM_N2", configD.PartNoR);
                var partNumTemp = configD.PartNoR.Substring(configD.PartNoR.Length - 4);
                code = $"{configD.PartIdentificationCode}{partNumTemp}{configD.SupplierCode}{serial}";
                paras.Add("EWM_N2", code);
            }
            return (paras, code);
        }

        private string GetSerial(int index)
        {
            var year = LabelCode.Substring(7, 1);
            var mouth = LabelCode.Substring(8, 1);
            var day = LabelCode.Substring(9, 2);

            //var station=ContainerServer.Container.Resolve<>

            return $"{year}{mouth}{day}{index.ToString("0000")}";
        }

        #endregion SQ

        #region BQKH

        private (Dictionary<string, string>, string) GetBQKHPara()
        {
            var config = ContainerServer.Container.Resolve<PrintConfigTotal>();
            var lxConfig = _dal.GetModel<BQKHRecord>(g => g.Code.Equals(LabelCode));
            var paras = new Dictionary<string, string>();
            paras.Add("LJH_N4", lxConfig.PartNumber);
            paras.Add("GYSDM_N4", lxConfig.SupplierCode);
            paras.Add("GKBJ_N4", lxConfig.ControlFlag);
            paras.Add("QDFS_N4", lxConfig.DriveMode);
            var batchCode = GetBatchCode(lxConfig.SerialNumber);
            paras.Add("PCBM_N4", batchCode);

            var code = $"{lxConfig.SupplierCode}{batchCode}K{lxConfig.PartNumber}";
            paras.Add("EWM_N4", code);
            var para = StationEnableConfig.GetPara();
            if (Cache.WorkDirection == WorkDirectionEnum.Left)
            {
                paras.Add("QHZY_N4", "L");
            }
            else
            {
                paras.Add("QHZY_N4", "R");
            }
            return (paras, code);
        }

        private string GetBatchCode(int index)
        {
            var years = DateTime.Now.Year.ToString().Substring(2);
            var mouths = DateTime.Now.Month.ToString("00");
            var days = DateTime.Now.Day.ToString("00");
            var indexs = index.ToString("00000");
            return $"{years}{mouths}{days}{indexs}";
        }

        #endregion BQKH

        #region BQLH

        private (Dictionary<string, string>, string) GetBQLHPara()
        {
            var lxConfig = _dal.GetModel<BQLHRecord>(g => g.Code.Equals(LabelCode));
            var paras = new Dictionary<string, string>();
            paras.Add("LJH_N3", lxConfig.PartNo);
            paras.Add("GYSDM_N3", lxConfig.SupplyNo);
            paras.Add("GKBJ_N3", lxConfig.ControllerCode);
            var batchCode = GetBQLHBatchCode(lxConfig.SerialNumber);
            paras.Add("PCBM_N3", batchCode);

            var code = $"{lxConfig.SupplyNo}{batchCode}K{lxConfig.PartNo}";
            paras.Add("EWM_N3", code);
            var para = StationEnableConfig.GetPara();
            if (Cache.WorkDirection == WorkDirectionEnum.Left)
            {
                paras.Add("QHZY_N3", "L");
            }
            else
            {
                paras.Add("QHZY_N3", "R");
            }
            return (paras, code);
        }

        private string GetBQLHBatchCode(int index)
        {
            var s = (byte)((DateTime.Now.Year - 2010) + 64);
            var year = Encoding.ASCII.GetString(new byte[] { s }); var mouths = DateTime.Now.Month.ToString("00");
            var days = DateTime.Now.Day.ToString("00");
            var indexs = index.ToString("00000");
            return $"{year}{mouths}{days}{indexs}";
        }

        #endregion BQLH

        #region WL

        private (Dictionary<string, string>, string) GetWLPara()
        {
            var config = ContainerServer.Container.Resolve<PrintConfigTotal>();
            var lxConfig = _dal.GetModel<WLRecord>(g => g.Code.Equals(LabelCode));
            var paras = new Dictionary<string, string>();
            paras.Add("LJH_N5", lxConfig.PartNo);
            paras.Add("BBH_N5", lxConfig.VersionNo);
            var productStr = GetProductData();
            paras.Add("SCRQ_N5", productStr);
            paras.Add("GYSDM_N5", lxConfig.SupplierCode);
            paras.Add("SCQFBSXX_N5", lxConfig.ProductionInfo);
            var serialNo = GetWLSerial(lxConfig.SerialNumber);
            paras.Add("XLH_N5", serialNo);
            var code = $"[>16{lxConfig.PartNo}V{lxConfig.VersionNo}D{productStr}{lxConfig.SupplierCode}S{lxConfig.ProductionInfo}N{serialNo}";
            paras.Add("EWM_N5", code);
            return (paras, code);
        }

        private string GetProductData()
        {
            var days = DateTime.Now.DayOfYear.ToString("000");
            var years = DateTime.Now.Year.ToString().Substring(2);
            return $"{days}{years}";
        }

        private string GetWLSerial(int index)
        {
            return index.ToString("00000");
        }

        #endregion WL

        #region 扫码枪相关

        private string _portStatus = "关闭";

        public string PortStatus
        {
            get { return _portStatus; }
            set => SetProperty(ref _portStatus, value);
        }

        private RelayCommand<string> _scanLinkCmd;

        public RelayCommand<string> ScanLinkCmd
        {
            get { return _scanLinkCmd ?? (_scanLinkCmd = new RelayCommand<string>(o => Init(o))); }
        }


        private PackageScanBarConfig _packageScanConfig;

        public PackageScanBarConfig PackageScanConfig
        {
            get { return _packageScanConfig; }
            set => SetProperty(ref _packageScanConfig, value);
        }

        private SerialPort _scanSerial;

        private void Init(string cmd)
        {
            if (cmd == "Open")
            {
                Task.Run(() =>
                {
                    if (PortStatus != "打开")
                    {
                        try
                        {
                            PortStatus = "打开中";
                            if (_scanSerial == null)
                            {
                                _scanSerial = new SerialPort();
                                _scanSerial.PortName = PackageScanConfig.Port;
                                _scanSerial.BaudRate = 115200;
                                _scanSerial.DataBits = 8;
                                _scanSerial.StopBits = StopBits.One;
                                _scanSerial.Parity = Parity.None;
                                _scanSerial.DataReceived += _scanSerial_DataReceived;
                            }
                            _scanSerial.Close();
                            _scanSerial.Open();
                            if (_scanSerial.IsOpen)
                            {
                                PortStatus = "打开";
                                //break;
                            }
                        }
                        catch (Exception ex)
                        {
                            PortStatus = "打开失败，请重试！";
                        }
                    }
                });
            }
            else
            {
                if (_scanSerial != null)
                {
                    _scanSerial?.Close();
                    if (!_scanSerial.IsOpen) PortStatus = "关闭";
                    _scanSerial?.Dispose();
                }
            }
        }

        private void _scanSerial_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            Thread.Sleep(200);

            var lenght = _scanSerial.BytesToRead;

            var bytes = new byte[lenght];
            _scanSerial.Read(bytes, 0, lenght);
            var str = Encoding.UTF8.GetString(bytes).Replace("\n", "").Replace("\r", "");
            if (Cache.EnterReplaceStatus)
            {
                MessageCenter.PublishAsync(nameof(PackageReplaceViewModel), str);
            }
            else
            {
                if (str.Length < 30)
                {
                    MessageCenter.PublishAsync(nameof(LableCompenstateViewModel), str);
                    MessageCenter.PublishAsync(nameof(WorkSituationViewModel), str);
                    MessageCenter.PublishAsync(nameof(HistoryViewModel), str);
                }
                else if (str.StartsWith("$"))
                {
                    MessageCenter.PublishAsync(nameof(HistoryViewModel), str);
                    MessageCenter.PublishAsync(nameof(ContinueBoxUpView), str);
                }
                else
                {
                    MessageCenter.PublishAsync(nameof(HistoryViewModel), str);
                }
            }
        }
        #endregion
    }
}